'''
Created on Feb 22, 2012

@author: daoxuandung
'''

"""
Utilities functions for Don't Repeat Yourself (DRY)
"""

import jinja2
import os
import datetime
from google.appengine.ext import ndb
from google.appengine.ext.ndb import Key
from google.appengine.ext.blobstore import BlobKey
from google.appengine.ext.ndb import model
from webapp2_extras.appengine.auth.models import User
from webapp2_extras import auth
from webapp2_extras.appengine.auth import models
import logging


def is_ajax(request):
    """
    Determine if a request is AJAX or normal request
    """
    if 'X-Requested-With' in request.headers:
        if request.headers['X-Requested-With'] == 'XMLHttpRequest':
            return True
        
    # If X-Requested-With is not inside, it's not AJAX request    
    return False


def jinja_environment(base="templates", child=""):
    """
    Create jinja_environment for a template at specified file structure
    
    Simplest use: put a file inside 'templates' folder, and try
        template = util.jinja_environment().get_template('upload-image.html')
    
    If template file inside a child folder, just replace child variable
        template = 
            util.jinja_environment(child="child_dir").get_template('upload-image.html')
    """
    base_paths = os.path.split(os.path.dirname(__file__))
    template_dir = os.path.join(base_paths[0], base, child)
    return jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir))


def get_current_user_key():
    """
    Return key of current user based on the session
    Will retrieve user_id from session then construct Key without datastore read
    """
    user = auth.get_auth().get_user_by_session()
    if (user is None):
        return None
    return model.Key(User, user['user_id'])

def get_current_user_name():
    """
    Return name of current user based on the session
    Temporarily return id
    """
    user = auth.get_auth().get_user_by_session()
    if (user is None):
        return None
    return user['user_id']


def ndb_to_dict(model, exclude=None):
    """
    Customization to default model.to_dict function
    Add id to a model dictionary
    Replace default Key of KeyProperty to id
    Remove class
    """
    default_exclude = ["class_", "password", "published", "privacy", "_is_new", "blob_key"]
    if exclude:
        default_exclude.append(exclude)
    dictionary = model.to_dict(exclude=default_exclude)
    dictionary['id'] = str(model.key.id())
    
    for k in dictionary:
        value = dictionary[k]
        
        # If a value is Key, change to id so that serialize to client easier
        if isinstance(value, Key):
            dictionary[k] = str(dictionary[k].id())
        
        elif isinstance(value, BlobKey):
            dictionary[k] = str(dictionary[k])
            
        # If datetime
        elif isinstance(value, datetime.datetime):
            dictionary[k] = value.isoformat()
                    
        # If property is KeyProperty, repeated=True
        elif isinstance(value, list):
            id_list = []
            for key in value:
                # If the object in list is key, push the id 
                if isinstance(key, Key):
                    id_list.append(str(key.id()))
                else:
                    id_list.append(str(key))
            dictionary[k] = id_list
            
    return dictionary

def ndb_to_list(model_list, exclude=None):
    """ 
    Return a list of dictionaries 
    from the list of model object
    """
    dict_list = []
    if model_list is not None and len(model_list) > 0:
        for e in model_list:
            dict_list.append(ndb_to_dict(e, exclude=exclude)) 
    return dict_list

def ndb_keys_to_dict_list(key_list, exclude=None):
    """ 
    Return a list of dictionaries 
    from the list of model object
    """
    dict_list = []
    if key_list is not None and len(key_list) > 0:
        for e in key_list:
            dict_list.append(ndb_to_dict(e.get(), exclude=exclude)) 
    return dict_list

def add_user_data (page, template_values):
    """ 
    Simple function to add user to current template value list 
    Prevent repeat the code over again in all page
    """
    if hasattr(page,"user_data"): 
        template_values["user_data"] =  page.user_data
    if hasattr(page,"user_friends"):
        template_values["user_friends"] =  page.user_friends
        
    return template_values

@ndb.tasklet
def get_url_async(url):
    ctx = ndb.get_context()
    result = yield ctx.urlfetch(url)
    if result.status_code == 200:
        raise ndb.Return(result.content)

    
@ndb.tasklet
def post_url_async(url, body, headers):
    ctx = ndb.get_context()
    result = yield ctx.urlfetch(url, body, 'POST', headers)
    if result.status_code == 200:
        raise ndb.Return(result.content)